﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace Casamiel.API.Application.Services
{
    /// <summary>
    /// Simple string cypher.
    /// </summary>
    public class SimpleStringCypher
    {
        private RijndaelManaged RM;
        /// <summary>
        /// 构造函数指定加密密钥
        /// </summary>
        /// <param name="secret">加密密钥</param>
        public SimpleStringCypher(String secret)
        {
            var keyBytes = PrepareAesKey(secret);
            RM = new System.Security.Cryptography.RijndaelManaged
            {
                Mode = System.Security.Cryptography.CipherMode.ECB,
                Padding = System.Security.Cryptography.PaddingMode.PKCS7,

                KeySize = 128,
                BlockSize = 128,
                Key = keyBytes,
                IV = keyBytes
            };
        }
        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="plaintext">需加密的字符串</param>
        /// <returns>加密后并经过 base64 编码的字符串</returns>
        public string Encrypt(string plaintext)
        {
            if (string.IsNullOrWhiteSpace(plaintext)) return null;
            Byte[] plaintextBytes = Encoding.UTF8.GetBytes(plaintext);
            ICryptoTransform cTransform = RM.CreateEncryptor();
            Byte[] resultArray = cTransform.TransformFinalBlock(plaintextBytes, 0, plaintextBytes.Length);
            return URLSafeBase64Reflow(Convert.ToBase64String(resultArray, 0, resultArray.Length));
        }

        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="codedText">需加密的字符串</param>
        /// <returns>加密后并经过 base64 编码的字符串</returns>
        public string Decrypt(string codedText)
        {
            if (string.IsNullOrWhiteSpace(codedText)) return null;

            Byte[] toDeryptArray = Convert.FromBase64String(AutomaticallyPad(NormalBase64Reflow(codedText)));
            ICryptoTransform cTransform = RM.CreateDecryptor();
            Byte[] resultArray = cTransform.TransformFinalBlock(toDeryptArray, 0, toDeryptArray.Length);
            return Encoding.UTF8.GetString(resultArray);
        }
      
        private static string AutomaticallyPad(string base64)
        {
            return base64.PadRight(base64.Length + (4 - base64.Length % 4) % 4, '=');
        }

        private static string URLSafeBase64Reflow(string base64)
        {
            return base64.Replace("=", String.Empty).Replace('+', '-').Replace('/', '_');
        }

        private static string NormalBase64Reflow(string base64)
        {
            return base64.Replace("=", String.Empty).Replace('-', '+').Replace('_', '/');
        }

        private static byte[] PrepareAesKey(string key)
        {
            Byte[] keyBinary = Convert.FromBase64String(AutomaticallyPad(NormalBase64Reflow(key)));
            var keyBytes = new byte[16];
            Array.Copy(keyBinary, keyBytes, Math.Min(keyBytes.Length, keyBinary.Length));
            return keyBytes;
        }
    }
}
